package cn.sprouting.tool;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;

import java.util.List;

/**
 * 随机各种编码
 *
 * @author ：LX（长沙麓谷）
 * @date 创建时间： 2021/11/5 10:44
 */
public class RandomCodeTool {

    /**
     * 常见的出版社编号范围
     */
    private static List<Integer[]> PUBLISHER_CODE_LIST = CollUtil.newArrayList(
            new Integer[]{5000, 5128},
            new Integer[]{5300, 5480},
            new Integer[]{5600, 5644},
            new Integer[]{80000, 80258},
            new Integer[]{80500, 80756},
            new Integer[]{81002, 81140}
    );
    /**
     * ISBN前缀编码
     */
    private static String ISBN_PREFIX = "978";

    /**
     * ISBN对应的国家或地区编码
     */
    private static String ISBN_COUNTRY_OR_REGION_CODE = "7";



    /**
     * 随机生成ISBN编号
     * ISBN一般指国际标准书号。 国际标准书号（International Standard Book Number），简称ISBN，是专门为识别图书等文献而设计的国际编号。
     * @param separator 是否带分隔符 -
     * @return
     */
    public static String getISBN(boolean separator){
        //随机获得1个出版商编码范围
        Integer[] publisherCode = RandomUtil.randomEle(PUBLISHER_CODE_LIST);
        //生成指定范围内的随机出版商编码
        String publisher = String.valueOf(RandomUtil.randomInt(publisherCode[0], publisherCode[1] + 1));
        //随机出版物序号(出版商编码+出版物序号总位数为8)
        String seq = RandomUtil.randomString(RandomUtil.BASE_NUMBER, 8 - publisher.length());

        String join = StrUtil.join("", ISBN_PREFIX, ISBN_COUNTRY_OR_REGION_CODE, publisher, seq);
        String checkDigit = getCheckDigit(join);
        if (separator){
            return StrUtil.join("-", ISBN_PREFIX, ISBN_COUNTRY_OR_REGION_CODE, publisher, seq, checkDigit);
        }

        return join + checkDigit;
    }

    /**
     * 随机生成国际商品编码
     * @return 国际商品编码
     */
    public static String getEAN() {
        //前缀：一般为690~692之间的一个数字
        String prefix = String.valueOf(RandomUtil.randomInt(690, 692));
        //随机制造商编码
        String manufacturer = RandomUtil.randomString(RandomUtil.BASE_NUMBER, 4);
        //随机商品编码
        String productCode = RandomUtil.randomString(RandomUtil.BASE_NUMBER, 5);
        //计算校验位
        String checkDigit = getCheckDigit(prefix + manufacturer + productCode);

        return prefix + manufacturer + productCode + checkDigit;
    }



    /**
     * 计算校验码
     *
     * @param toCheck 待计算的数字字符串
     * @return 校验码
     */
    private static String getCheckDigit(String toCheck) {
        int total = 0;
        for (int i = 1; i <= toCheck.length(); i++) {
            //偶数位因子：3，奇数位因子：1
            int factor = (i % 2 == 0) ? 3 : 1;
            //依次取出每位数
            int x = Integer.parseInt(String.valueOf(toCheck.charAt(i - 1)));
            //每位数*因子
            int chk = x * factor;
            //求和
            total += chk;
        }
        //总和除以10取余数
        int mod = total % 10;
        //余数=0时校验码为0，余数大于0时校验码为10-余数
        int digit = (mod == 0) ? 0 : 10 - mod;
        return String.valueOf(digit);
    }

}
